package owlapps2012.owlToSql.base;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Author: Piotr Nowara<br>
* piotrnowara@gmail.com<br>
* code made available under Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.html)<br>
* copyright 2012, Piotr Nowara<br>
*/
public class TextProcessingUtils 
{
	public static Pattern pattern = Pattern.compile("(and|or){0,}\\s{0,}(\\({0,}not\\s{0,}\\(){0,}\\s{0,}(\\({0,})([a-zA-Z-_0-9\\.]{1,}\\sand\\s){0,}\\s{0,}([a-zA-Z-_0-9\\.]{1,}) (some ([a-zA-Z-_0-9\\.]{1,}(\\[(=|>|<|>=|<=)([0-9]{1,})\\]){0,1}){0,1}|min [0-9]{1,}|(value ([0-9\\.]{1,}|\"([^\"]{0,})\"(\\^\\^(integer|int|string)){0,})))\\s{0,}(\\){0,})");

	public static Pattern cRestrPattern = Pattern.compile("((S[0-9]{1,}L)([0-9]{1,}))\\s{1,}WHERE");
	public static final Pattern patternForGroupOfBrackets = Pattern.compile("\\s{0,}\\({1,}");
	public static final Pattern oBracketPattern = Pattern.compile("\\(");
	public static final Pattern eBracketPattern = Pattern.compile("\\)");
	public static final Pattern classNameWithOR = Pattern.compile("^[A-Z][a-zA-Z_\\-0-9]{1,}\\s{0,}or|\\([A-Z][a-zA-Z_\\-0-9]{1,}\\s{0,}or");
	public static final Pattern classNameNotAtBeginning = Pattern.compile("(and|or|not){1,}\\s{0,}\\({0,}\\s{0,}[A-Z][a-zA-Z_\\-0-9]{1,}\\s{0,}\\){0,}(and|or){0,}");
	public static final Pattern owlMin1Pattern = Pattern.compile("\\s{1,}min 1\\s{1,}");
	public static final Pattern plIPattern = Pattern.compile("\\s{1,}i\\s{1,}");
	public static final Pattern plLUBPattern = Pattern.compile("\\s{1,}lub\\s{1,}");
	public static final Pattern plKONIECZNIE1Pattern = Pattern.compile("\\s{1,}koniecznie\\s{1,}");
	public static final Pattern plNIEPattern = Pattern.compile("\\s{1,}nie\\s{1,}\\(");
	public static final Pattern plNIEPattern2 = Pattern.compile("\\s{1,}(\\({1,})nie\\s{1,}\\(");
	public static final Pattern owlSAFEPattern = Pattern.compile("value \"[^\"]{0,}(\\(|(\\s{1,}(min 1 |nie\\s{1,}\\(|\\(nie\\s{1,}\\(|i |lub |koniecznie )))[^\"]{0,}\"");
	public static final Pattern notPattern = Pattern.compile("not\\s{0,}\\(");
	public static final Pattern numericPattern = Pattern.compile("[0-9]{1,}");
	public static final Pattern numericBetweenPattern = Pattern.compile("([0-9]{1,})_and_([0-9]{1,})");

	/*
	 * Returns -1 if the bracket is not closed in the given piece of text
	 */
	public static int determineBracketRange(String text, int startIndex) throws OwlToSqlTransformationException 
	{
		if(text.charAt(startIndex) != '(')
			throw new OwlToSqlTransformationException("Character '"+text.charAt(startIndex)+"' encountered at specified start index is not a bracket!");
		
		int i = -1;
		int range = -1;
		int level = 0;
		for(char ch:text.substring(startIndex).toCharArray()) 
		{
			i++;
			if(ch == '(')
				level++;
			else if(ch == ')')
				level--;
			
			if(level == 0)
			{
				range = i;
				break;
			}
		}
	
		if(range > -1)
			return range + startIndex;
		else
			return range;
	}

	public static int getEndIndexOfNextGroupsOfBrackets(String text) 
	{
		Matcher m = patternForGroupOfBrackets.matcher(text);
		if(m.find())
			return m.end();
		else 
			return -1;
//		return patternForGroupOfBrackets.matcher(text).end();
	}

	public static boolean checkIfCloseBracket(ArrayList<Integer> listOfBracketsToBeAdded,Object endIndexOfNextGroupsOfBrackets)
	{
		// TODO Auto-generated method stub
		return false;
	}
	
	public static boolean checkIfNested(ArrayList<OWLMinRestriction> listOfMinRestrictions) 
	{
		boolean isNested = false;
		for(int i=0; i<listOfMinRestrictions.size();i++)
		{
			if(!listOfMinRestrictions.get(i).isTransformed())
			{
				isNested = true;
				break;
			}
		}
		return isNested;
	}

	public static String addMissingBracketsMinClause(String transformedSqlFragment) 
	{
		Matcher m = oBracketPattern.matcher(transformedSqlFragment);
		int oCount = 0;
		while(m.find())
			oCount++;
		m = eBracketPattern.matcher(transformedSqlFragment);
		int eCount = 0;
		while(m.find())
			eCount++;
		for(int j=0;j<(oCount - eCount);j++)
			transformedSqlFragment = transformedSqlFragment.concat(")");		
		return transformedSqlFragment;
	}
	
	public static String returnMissingBrackets(String s) 
	{
		String missingBrackets = "";
		Matcher m = oBracketPattern.matcher(s);
		int oCount = 0;
		while(m.find())
			oCount++;
		m = eBracketPattern.matcher(s);
		int eCount = 0;
		while(m.find())
			eCount++;
		for(int j=0;j<(oCount - eCount);j++)
			missingBrackets = missingBrackets.concat(")");		
		return missingBrackets;
	}

	public static String determineLatestTableOfSpecifiedLevel(ArrayList<String> listOfTableNames, int levDiff) throws OwlToSqlTransformationException 
	{
		int maxIndexWithDesiredLevel = 0;
		Pattern patternForLevels = Pattern.compile("S([0-9]{1,})L"+levDiff);
		for(int i=0;i<listOfTableNames.size();i++)
		{
			Matcher m = patternForLevels.matcher(listOfTableNames.get(i));
			if(m.find())
			{
				int tableIndex = Integer.parseInt(m.group(1));
				if(tableIndex > maxIndexWithDesiredLevel)
					maxIndexWithDesiredLevel = tableIndex;
			}
		}
		if(maxIndexWithDesiredLevel > 0)
			return "S"+maxIndexWithDesiredLevel+"L"+levDiff;
		else
			throw new OwlToSqlTransformationException("Unable to find a qualifier with desired level: "+levDiff);
	}

	public static String determineLogicalOperator(String explicitLogicalOperator, int matchCount) 
	{
		if(matchCount > 1)
			return explicitLogicalOperator == null ? "AND" : explicitLogicalOperator;
		else
			return "";
	}
	
	public static int parseNumberOfDays(String name) throws OwlToSqlTransformationException 
	{
		Matcher m = numericPattern.matcher(name);
		if(m.find())
			return Integer.parseInt(m.group());
		else
			throw new OwlToSqlTransformationException("Number not found!");
	}

	public static String parseNumberOfDaysBetween(String name) throws OwlToSqlTransformationException 
	{
		Matcher m = numericBetweenPattern.matcher(name);
		if(m.find())
			return m.group(1).concat(" AND ").concat(m.group(2));
		else
			throw new OwlToSqlTransformationException("Numbers not found!");
	}
	
	public static String getTableNameByQualifier(String transformedExpression, String q) 
	{
		Matcher m = Pattern.compile("\\s{1}([^\\s]{1,})\\s{1,}".concat(q)).matcher(transformedExpression);
		if(m.find())
			return m.group(1);
		else
		{
			System.out.println("Table name not found for qualifier: "+q);
			return null;
		}

	}

	public static String getTableNameByQualifier(ArrayList<SQLQualifier> listOfQualifiers, String name) 
	{
		for(int i = 0;i<listOfQualifiers.size();i++)
		{
			if(listOfQualifiers.get(i).getQualifierName().equals(name))
				return listOfQualifiers.get(i).getTableName();
		}
		System.out.println("Table name not found for qualifier: "+name);
		return null;
	}
}
